﻿/*  ------------------------------------------------------------------------
	 NQ Common Services Library
	 
	 Homepage: http://www.awzhome.de/
	 ------------------------------------------------------------------------
	 
	 The contents of this file are subject to the Mozilla Public License
	 Version 1.1 (the "License"); you may not use this file except in
	 compliance with the License. You may obtain a copy of the License at
	 http://www.mozilla.org/MPL/
	 
	 Software distributed under the License is distributed on an "AS IS"
	 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	 License for the specific language governing rights and limitations
	 under the License.
	
	 The Original Code is code of NQ Common Services Library.

	 The Initial Developer of the Original Code is Andreas Weizel.
	 Portions created by the Initial Developer are
	 Copyright (C) 2006-2011 Andreas Weizel. All Rights Reserved.
	 
	 Contributor(s): (none)
	 
	 Alternatively, the contents of this file may be used under the terms
	 of the GNU General Public License Version 2.0 or later (the "GPL"),
	 or the GNU Lesser General Public License Version 2.1 or later (the
	 "LGPL"), in which case the provisions of the GPL or the LGPL are
	 applicable instead of those above. If you wish to allow use of your
	 version of this file only under the terms of the GPL or the LGPL and
	 not to allow others to use your version of this file under the MPL,
	 indicate your decision by deleting the provisions above and replace
	 them with the notice and other provisions required by the GPL or the
	 LGPL. If you do not delete the provisions above, a recipient may use
	 your version of this file under the terms of any of the MPL, the GPL
	 or the LGPL.
	 ------------------------------------------------------------------------
*/

using System;
using System.Collections.Generic;
using System.Linq;
using AvalonDock;
using AWZhome.NQ.CommonServices.Visual;
using AWZhome.NQ.Core;
using AWZhome.NQ.Core.Fluent;
using System.Windows.Forms.Integration;
using System.IO;
using System.Reflection;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.Xml;

namespace AWZhome.NQ.CommonServices
{
	[NQExportedService]
	public class ViewManagerService : Services.IViewManagerService
	{
		private IContainer _parentContainer = null;
		private IResourceManager _servRes = null;
		private IBarManager _servBar = null;
		private IPersistManager _servPersist = null;

		private Dictionary<string, IView> _views = new Dictionary<string, IView>();
		private Dictionary<string, DockableContent> _dockableContents = new Dictionary<string, DockableContent>();
		private Dictionary<string, DocumentContent> _documentContents = new Dictionary<string, DocumentContent>();

		private List<ManagedContent> _leftDockableContents = new List<ManagedContent>();
		private List<ManagedContent> _rightDockableContents = new List<ManagedContent>();
		private List<ManagedContent> _topDockableContents = new List<ManagedContent>();
		private List<ManagedContent> _bottomDockableContents = new List<ManagedContent>();
		private List<ManagedContent> _innerDocumentContents = new List<ManagedContent>();

		private IView _activeView = null;
		private ViewManagerDock _viewManDock = null;
		private IView _closingView = null;
		//private string _closingDockViewName = null;
		private bool _suppressContentHide = false;

		public ViewManagerService(IContainer parent)
		{
			_parentContainer = parent;
			Panel parentControl = _parentContainer.ClientAreaObject as Panel;

			_servRes = ServiceCore
				.Get<Services.IResourceService>()
				.To;
			_servBar = _parentContainer.BarService;
			_servPersist = ServiceCore
				.Get<Services.IPersistService>()
				.To;

			_servBar.ItemClicked += _servBar_ItemClicked;

			if (parentControl != null)
			{
				// Create ViewManagerDock control
				_viewManDock = new ViewManagerDock();
				_viewManDock.DataContext = this;
				parentControl.Children.Add(_viewManDock);
				_viewManDock.Visibility = Visibility.Visible;
				_viewManDock.DummyGrid.Loaded += _viewManDock_Loaded;
				_viewManDock.DockingManager.ActiveContentChanged += DockingManager_ActiveContentChanged;
				_viewManDock.DockingManager.DeserializationCallback = this.DockingManagerDeserializationCallback;
				CommandManager.AddPreviewExecutedHandler(_viewManDock.DockingManager, new ExecutedRoutedEventHandler(this.ViewManagerService_CommandPreviewExecuted));
			}

			// Create menus
			this.CreateMenus();
		}

		#region INQViewManagerService Member

		public event EventHandler<ActiveViewChangedEventArgs> ActiveViewChanged;

		public void AddView(IView newView)
		{
			this.AddView(newView, true, true);
		}

		public void AddView(IView newView, bool activate)
		{
			this.AddView(newView, activate, true);
		}

		public void RemoveView(string viewName)
		{
			if (_views.ContainsKey(viewName))
			{
				IView delview = _views[viewName];

				// Check if the view can be closed
				if (delview.CanBeClosed)
				{
					if (delview.RequestClosing())
					{
						if (_documentContents.ContainsKey(viewName))
						{
							// Handle a DocumentContent
							DocumentContent viewContent = _documentContents[viewName];
							if (_closingView == null)
							{
								_closingView = delview;
								if (!_suppressContentHide)
								{
									viewContent.Close();
								}
								if (_innerDocumentContents.Contains(viewContent))
								{
									_innerDocumentContents.Remove(viewContent);
								}
								_closingView = null;
							}

							_documentContents.Remove(viewName);
						}
						else if (_dockableContents.ContainsKey(viewName))
						{
							// Handle a DockableContent
							DockableContent viewContent = _dockableContents[viewName];
							if (_closingView == null)
							{
								_closingView = delview;
								if (!_suppressContentHide)
								{
									viewContent.Hide();
									//_viewManDock.DockingManager.Hide(viewContent);
								}

								DockableContentState dockableState = new DockableContentState();
								AnchorStyle anchorStyle = new AnchorStyle();
								this.GetDockableStateFromDisplayMode(delview.DisplayMode, ref dockableState, ref anchorStyle);
								var dockableCollection = this.GetDockableCollectionFromAnchorStyle(anchorStyle);
								if (dockableCollection != null)
								{
									if (dockableCollection.Contains(viewContent))
									{
										dockableCollection.Remove(viewContent);
									}
								}
								else
								{
									// Look for the DockableContent in inner document pane
									if (_innerDocumentContents.Contains(viewContent))
									{
										_innerDocumentContents.Remove(viewContent);
									}
								}

								_closingView = null;
							}

							// Empty the DockableContent and cache it
							viewContent.Content = null;
							viewContent.Title = "<<cached>>";
							viewContent.ToolTip = null;
							viewContent.StateChanged -= this.dockContent_StateChanged;

							_dockableContents.Remove(viewName);
						}

						// Let the view save its settings
						delview.SaveContents(ViewSaveReason.ExplicitlyClosed);

						// Delete the view object and its panel
						delview.ViewManager = null;
						_views.Remove(viewName);

						if (this.CountByDisplayMode(ViewDisplayMode.InClientArea) == 0)
						{
							// The last view is about to be closed, clear active view reference to be safe
							this.ActiveView = null;
						}

						// Remove item from window menu
						_servBar.GetItem("mnuWindow").RemoveItem("mnuWindow.Item." + viewName);
						_servBar.RemoveItem("mnuWindow.Item." + viewName);

						// Hide/show some menu items depending on open view count
						int tabCount = this.CountByDisplayMode(ViewDisplayMode.InClientArea);
						_servBar.GetItem("mnuWindow.CloseCurrent").ItemEnabled = (tabCount > 0);
						_servBar.GetItem("mnuWindow.CloseAll").ItemEnabled = (tabCount > 0);
						_servBar.GetItem("mnuWindow.Sep1").ItemVisible = (tabCount > 0);
					}
				}
			}
			else
			{
				// We don't know that view name
				this.RaiseViewNotFoundException(viewName);
			}
		}

		public void UpdateView(IView view, bool internalChange)
		{
			if (_views.ContainsKey(view.Name))
			{
				// Update DockPane from view properties
				ManagedContent manContent = null;

				if (_dockableContents.ContainsKey(view.Name))
				{
					DockableContent dockContent = _dockableContents[view.Name];
					manContent = dockContent;

					bool foundContainer = false;
					ViewDisplayMode curDisplayMode = view.DisplayMode;
					if (dockContent.ContainerPane != null)
					{
						if (dockContent.ContainerPane is DockablePane)
						{
							curDisplayMode = this.GetDisplayModeFromDockableState(dockContent.State, ((DockablePane) dockContent.ContainerPane).Anchor);
							foundContainer = true;
						}
						else if (dockContent.ContainerPane is DocumentPane)
						{
							// TODO A DocumentPane can also be floating, but how to determine this?
							curDisplayMode = ViewDisplayMode.InClientArea;
							foundContainer = true;
						}
					}
					if (!foundContainer || (view.DisplayMode != curDisplayMode))
					{
						if (internalChange)
						{
							// This will probably result in a recursive call of UpdateView, but it doesn't matter
							view.DisplayMode = curDisplayMode;
						}
						else
						{
							DockableContentState dockableState = new DockableContentState();
							AnchorStyle anchorStyle = new AnchorStyle();
							this.GetDockableStateFromDisplayMode(view.DisplayMode, ref dockableState, ref anchorStyle);

							if (dockableState == DockableContentState.Document)
							{
								// Show as document
								//_viewManDock.DockingManager.Show(dockContent, dockableState);
								//dockContent.State = dockableState;
								dockContent.ShowAsDocument(_viewManDock.DockingManager);
								_innerDocumentContents.Add(dockContent);
							}
							else if (dockableState == DockableContentState.DockableWindow)
							{
								// Show as floating window
								dockContent.ShowAsFloatingWindow(_viewManDock.DockingManager, true);
								_innerDocumentContents.Add(dockContent);
							}
							else
							{
								//_viewManDock.DockingManager.Show(dockContent, dockableState, anchorStyle);
								dockContent.Show(_viewManDock.DockingManager, anchorStyle);
							}
						}
					}
				}
				else if (_documentContents.ContainsKey(view.Name))
				{
					DocumentContent dockContent = _documentContents[view.Name];
					manContent = dockContent;
					ViewDisplayMode curDisplayMode = ViewDisplayMode.InClientArea;

					if (view.DisplayMode != curDisplayMode)
					{
						if (internalChange)
						{
							// This will probably result in a recursive call of UpdateView, but it doesn't matter
							view.DisplayMode = curDisplayMode;
						}
					}

					//_viewManDock.DockingManager.Show(dockContent);
					dockContent.Show(_viewManDock.DockingManager);
				}

				manContent.IsCloseable = view.CanBeClosed;
				manContent.Title = view.DisplayName;
				manContent.Icon = view.Icon;
				if (manContent is DocumentContent)
				{
					((DocumentContent) manContent).InfoTip = view.ToolTip;
				}
				_servBar.GetItem("mnuWindow.Item." + view.Name).ItemVisible = (view.DisplayMode == ViewDisplayMode.InClientArea);
			}

			// Hide/show some menu items depending on open view count
			int tabCount = this.CountByDisplayMode(ViewDisplayMode.InClientArea);
			_servBar.GetItem("mnuWindow.CloseCurrent").ItemEnabled = (tabCount > 0);
			_servBar.GetItem("mnuWindow.CloseAll").ItemEnabled = (tabCount > 0);
			_servBar.GetItem("mnuWindow.Sep1").ItemVisible = (tabCount > 0);

			_parentContainer.Update();
		}

		public void MoveView(IView view, IViewManager destManager)
		{
		}

		public int CountByDisplayMode(ViewDisplayMode displayMode)
		{
			int count = 0;
			foreach (IView view in _views.Values)
			{
				if (view.DisplayMode == displayMode)
				{
					count++;
				}
			}

			return count;
		}

		public void LoadSettings()
		{

		}

		public void SaveSettings()
		{
			// Save the settings of all open views
			foreach (IView view in _views.Values)
			{
				view.SaveContents(ViewSaveReason.ContainerClosed);
			}

			this.SaveViewManagerLayout();
		}

		public IView ActiveView
		{
			get
			{
				return _activeView;
			}
			set
			{
				if (value != _activeView)
				{
					if (value != null)
					{
						if (_views.ContainsValue(value))
						{
							if (value.DisplayMode == ViewDisplayMode.InClientArea)
							{
								// Activate the view
								if (_dockableContents.ContainsKey(value.Name))
								{
									_dockableContents[value.Name].Activate();
								}
								else if (_documentContents.ContainsKey(value.Name))
								{
									_documentContents[value.Name].Activate();
								}
							}
						}
						else
						{
							// View not found
							RaiseViewNotFoundException(value.Name);
						}
					}
					else
					{
						// The new view is "null"
						_activeView = null;
						this.OnActiveViewChanged(_activeView, null);
					}
				}
			}
		}

		public ISession ActiveSession
		{
			get
			{
				if (_activeView != null)
				{
					return _activeView.Session;
				}
				else
				{
					// Get default session
					ISessionManager sessionManager = ServiceCore
						.Get<Services.ISessionManagerService>()
						.To;
					return sessionManager.DefaultSession;
				}
			}
		}

		#endregion

		public IContainer Container
		{
			get
			{
				return _parentContainer;
			}
		}

		#region INQCollectionService<string,INQViewService> Member

		public IView this[string key]
		{
			get
			{
				if (_views.ContainsKey(key))
				{
					return _views[key];
				}
				else
				{
					return null;
				}
			}
		}

		public int Count
		{
			get
			{
				return _views.Count;
			}
		}

		#endregion

		#region IEnumerable<INQViewService> Member

		public IEnumerator<IView> GetEnumerator()
		{
			return ((IEnumerable<IView>) _views.Values).GetEnumerator();
		}

		#endregion

		#region IEnumerable Member

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return ((System.Collections.IEnumerable) _views.Values).GetEnumerator();
		}

		#endregion

		#region Internal and public members

		internal List<ManagedContent> LeftDockableContents
		{
			get
			{
				return _leftDockableContents;
			}
		}

		internal List<ManagedContent> RightDockableContents
		{
			get
			{
				return _rightDockableContents;
			}
		}

		internal List<ManagedContent> TopDockableContents
		{
			get
			{
				return _topDockableContents;
			}
		}

		internal List<ManagedContent> BottomDockableContents
		{
			get
			{
				return _bottomDockableContents;
			}
		}

		internal List<ManagedContent> InnerDocumentContents
		{
			get
			{
				return _innerDocumentContents;
			}
		}

		#endregion

		#region Private members

		private ManagedContent AddView(IView newView, bool activate, bool setLayout)
		{
			IView oldview = _activeView;

			// Exit if this view is already here
			if (_views.ContainsKey(newView.Name))
			{
				return null;
			}

			// Remove the view from any other view manager
			if (newView.ViewManager != null)
			{
				newView.ViewManager.RemoveView(newView.Name);
			}

			// Add the view object to internal list
			_views.Add(newView.Name, newView);
			newView.ViewManager = this;

			// Display tab container
			if (_views.Count > 0)
			{
				_servBar.GetItem("mnuWindow.CloseCurrent").ItemEnabled = true;
				_servBar.GetItem("mnuWindow.CloseAll").ItemEnabled = true;
				_servBar.GetItem("mnuWindow.Sep1").ItemVisible = true;
			}

			// Create item in window menu (must be done before creating the dock pane)
			string windowItemKey = "mnuWindow.Item." + newView.Name;
			try
			{
				IBarItem viewMenuItem = _servBar.CreateItem(windowItemKey, BarItemType.MenuItem);
				viewMenuItem.ItemText = newView.DisplayName;
				_servBar.GetItem("mnuWindow").InsertItem(windowItemKey, "mnuWindow.Sep1", false);
			}
			catch (BarDefinitionException ex)
			{
				ServiceCore.Log.From(this).Error(ex);
			}

			ManagedContent manContent = null;
			if (newView.IsDocument)
			{
				CSDocumentContent dockContent = new CSDocumentContent(this);

				// Floating for DocumentContents is currently disabled,
				// because we can't handle the change between Docked <-> Floating for DocumentContents
				// in AvalonDock. Therefore we can't persist it.
				//dockContent.IsFloatingAllowed =
				//	((newView.DockingType & NQViewDisplayMode.Floating) == NQViewDisplayMode.Floating);

				dockContent.View = newView;
				_documentContents.Add(newView.Name, dockContent);
				manContent = dockContent;
			}
			else
			{
				CSDockableContent dockContent = null;
				dockContent = new CSDockableContent(this);
				dockContent.View = newView;
				dockContent.DockableStyle = this.DockableStyleFromDisplayModes(newView.DockingType);
				dockContent.StateChanged += dockContent_StateChanged;
				CommandManager.AddPreviewExecutedHandler(_viewManDock.DockingManager, this.ViewManagerService_CommandPreviewExecuted);
				_dockableContents.Add(newView.Name, dockContent);

				manContent = dockContent;
			}

			// If the view's control is a WinForms control, create a WindowsFormsHost around it
			if (newView.DisplayedObject is System.Windows.Forms.Control)
			{
				WindowsFormsHost winFormsHost = new WindowsFormsHost();
				winFormsHost.Child = (System.Windows.Forms.Control) newView.DisplayedObject;
				((System.Windows.Forms.Control) newView.DisplayedObject).Visible = true;
				winFormsHost.Visibility = Visibility.Visible;
				manContent.Content = winFormsHost;
			}
			else if (newView.DisplayedObject is System.Windows.Controls.Control)
			{
				// The displayed control is a WPF control
				manContent.Content = newView.DisplayedObject;
			}

			if (setLayout)
			{
				// Load layout, that has been saved the last time this type of view was open
				this.LoadViewLayout(newView);

				this.UpdateView(newView, false);

				if (manContent is DockableContent)
				{
					if (manContent.ContainerPane != null)
					{
						// Fix the minimal size of the pane
						if ((newView.DisplayMode == ViewDisplayMode.DockedLeft) || (newView.DisplayMode == ViewDisplayMode.DockedRight))
						{
							if (ResizingPanel.GetResizeWidth(manContent.ContainerPane).Value < 50)
							{
								ResizingPanel.SetResizeWidth(manContent.ContainerPane, new GridLength(200));
							}
						}
						else if ((newView.DisplayMode == ViewDisplayMode.DockedTop) || (newView.DisplayMode == ViewDisplayMode.DockedBottom))
						{
							if (ResizingPanel.GetResizeHeight(manContent.ContainerPane).Value < 50)
							{
								ResizingPanel.SetResizeHeight(manContent.ContainerPane, new GridLength(200));
							}
						}
					}
				}
			}

			// Let the view load its settings
			newView.LoadContents();

			//if (setLayout)
			//{
			if (newView.DisplayMode == ViewDisplayMode.InClientArea)
			{
				if (activate)
				{
					// Set the new view active
					this.ActiveView = newView;
					//manContent.SetAsActive();
					manContent.Activate();
				}
				else
				{
					if (oldview != null)
					{
						if (_dockableContents.ContainsKey(oldview.Name))
						{
							//_dockableContents[oldview.ViewName].SetAsActive();
							_dockableContents[oldview.Name].Activate();
						}
						else if (_documentContents.ContainsKey(oldview.Name))
						{
							//_documentContents[oldview.ViewName].SetAsActive();
							_documentContents[oldview.Name].Activate();
						}
					}
				}
			}
			else if (newView.DisplayMode == ViewDisplayMode.Floating)
			{
				// Floating windows can also be activated
				if (activate)
				{
					manContent.Activate();
				}
			}
			//}

			return manContent;
		}

		private void _viewManDock_Loaded(object sender, RoutedEventArgs e)
		{
			this.LoadViewManagerLayout();
		}

		private void _servBar_ItemClicked(object sender, BarItemClickedEventArgs e)
		{
			switch (e.Item.ItemKey)
			{
				case "mnuWindow.CloseCurrent":
					if (_activeView != null)
					{
						// Close current view
						RemoveView(_activeView.Name);
					}
					break;

				case "mnuWindow.CloseAll":
					// Close all views
					string[] viewkeys = new string[_views.Count];
					_views.Keys.CopyTo(viewkeys, 0);
					for (int i = 0; i < viewkeys.Length; i++)
					{
						RemoveView(_views[viewkeys[i]].Name);
					}
					break;

				//case "cmnuViewManagerTab.CloseCurrent":
				//  if (_contextView != null)
				//  {
				//    // Close current tab
				//    RemoveView(contextView.ViewName);
				//    contextView = null;
				//  }
				//  break;

				//case "cmnuViewManagerTab.CloseOther":
				//  // Close all tabs besides the one which is selected
				//  if (contextView != null)
				//  {
				//    List<INQViewService> delviews = new List<INQViewService>();
				//    foreach (INQViewService viewItem in _views.Values)
				//    {
				//      if ((viewItem != contextView) && (viewItem.DisplayMode == contextView.DisplayMode))
				//      {
				//        delviews.Add(viewItem);
				//      }
				//    }
				//    for (int i = 0; i < delviews.Count; i++)
				//    {
				//      RemoveView(delviews[i].ViewName);
				//    }
				//    contextView = null;
				//  }
				//  break;

				default:
					if (e.Item.ItemKey.StartsWith("mnuWindow.Item."))
					{
						// Activate the view
						this.ActiveView = _views[e.Item.ItemKey.Substring("mnuWindow.Item.".Length)];
					}
					break;
			}
		}

		private void dockContent_StateChanged(object sender, RoutedEventArgs e)
		{
			if (sender is DockableContent)
			{
				if (((DockableContent) sender).State != DockableContentState.Hidden)
				{
					IView senderView = this.GetViewFromManagedContent((ManagedContent) sender);
					this.UpdateView(senderView, true);
				}
				else
				{
					// TODO What to do with DockableContentState.Hidden? It happens when FloatingWindows are closed.
				}
			}
		}

		private void DockingManager_ActiveContentChanged(object sender, EventArgs e)
		{
			bool suppressEvents = false;

			// Get tab from view
			IView selview = null;
			IView oldview = _activeView;

			// Get the view, the active document belongs to
			selview = this.GetViewFromManagedContent(_viewManDock.DockingManager.ActiveContent);
			if (selview != null)
			{
				if (selview.DisplayMode == ViewDisplayMode.InClientArea)
				{
					if (oldview != null)
					{
						// Hide the view
						oldview.Deactivate(selview);
						string itemname = "mnuWindow.Item." + oldview.Name;
						if (_servBar.ItemExists(itemname))
						{
							_servBar.GetItem(itemname).ItemChecked = false;
						}
					}
					// Select the view
					_activeView = selview;
					if (_activeView != null)
					{
						_activeView.Activate(oldview);
						// Make the new view visible
						string itemname = "mnuWindow.Item." + _activeView.Name;
						if (_servBar.ItemExists(itemname))
						{
							_servBar.GetItem(itemname).ItemChecked = true;
						}
					}
				}
				else
				{
					suppressEvents = true;
				}
			}

			if (!suppressEvents)
			{
				this.OnActiveViewChanged(oldview, selview);
			}
		}

		private void ViewManagerService_CommandPreviewExecuted(object sender, ExecutedRoutedEventArgs e)
		{
			//if (e.Command == ApplicationCommands.Close || e.Command == ManagedContentCommands.Close)
			//{
			//   ManagedContent manContent = null;
			//   if (e.Source is ManagedContent)
			//   {
			//      manContent = (ManagedContent) e.Source;
			//   }
			//   else if (e.Source is Pane)
			//   {
			//      manContent = (ManagedContent) ((Pane) e.Source).SelectedItem;
			//   }

			//   if (manContent != null)
			//   {
			//      this.OnViewContentClosed(manContent);
			//   }
			//}
		}

		private IView GetViewFromManagedContent(ManagedContent managedContent)
		{
			// Search for the view that ManagedContent belongs to
			var views = from v in _views.Values
							where (_dockableContents.ContainsKey(v.Name) && (_dockableContents[v.Name] == managedContent))
							select v;
			if (views.Count() == 0)
			{
				// No DockableContent found, so we try the DocumentContents
				views = from v in _views.Values
						  where (_documentContents.ContainsKey(v.Name) && (_documentContents[v.Name] == managedContent))
						  select v;
			}
			return (views.Count() > 0) ? views.First() : null;
		}

		private void OnActiveViewChanged(IView oldview, IView newview)
		{
			// Set visibility of dependent bar items in the container
			if (_parentContainer.BarService != null)
			{
				if (oldview != null)
				{
					SetBarItemVisibility(oldview, newview, false);
				}
				if (newview != null)
				{
					SetBarItemVisibility(newview, oldview, true);
				}
			}

			// Set the window menu item of the current view to top
			if (newview != null)
			{
				string windowItemKey = "mnuWindow.Item." + newview.Name;
				_servBar.GetItem("mnuWindow").RemoveItem(windowItemKey);
				_servBar.GetItem("mnuWindow").InsertItem(windowItemKey, "mnuWindow.Sep1", false);
			}

			_parentContainer.Update();

			if ((this.ActiveViewChanged != null) && (oldview != newview))
			{
				this.ActiveViewChanged(this, new ActiveViewChangedEventArgs(oldview, newview));
			}
		}

		internal bool OnViewContentClosed(ManagedContent manContent)
		{
			bool retvalue = false;

			// Fix the active content, if it's null
			//if (_viewManDock.DockingManager.ActiveContent == null)
			//{
			//  INQViewService tempview = this.ActiveView;
			//  this.ActiveView = null;
			//  this.ActiveView = tempview;
			//}

			IView view = this.GetViewFromManagedContent(manContent);
			if ((view != null))
			{
				//if (manContent == _viewManDock.DockingManager.ActiveContent)
				//{
				// This event is often executed many times for the same closing content.
				// Prevent the code from trying to remove the same view several times.
				if (_views.ContainsKey(view.Name))
				//if (view.ViewName != _closingDockViewName)
				{
					//  _closingDockViewName = view.ViewName;

					if (_closingView != view)
					{
						// Remove the view
						_suppressContentHide = true;
						this.RemoveView(view.Name);
						_suppressContentHide = false;

						retvalue = true;
					}
				}
				//}
			}

			return retvalue;
		}

		private List<ManagedContent> GetDockableCollectionFromAnchorStyle(AnchorStyle anchorStyle)
		{
			switch (anchorStyle)
			{
				case AnchorStyle.Left:
					return this.LeftDockableContents;
				case AnchorStyle.Right:
					return this.RightDockableContents;
				case AnchorStyle.Top:
					return this.TopDockableContents;
				case AnchorStyle.Bottom:
					return this.BottomDockableContents;
				default:
					return null;
			}
		}

		private DockablePane GetDockablePaneFromAnchorStyle(AnchorStyle anchorStyle)
		{
			DockablePane pane = null;

			if ((anchorStyle == AnchorStyle.Top) || (anchorStyle == AnchorStyle.Bottom))
			{
				// Search for a DockablePane with the given AnchorStyle
				foreach (UIElement element in _viewManDock.VerticalResizingPanel.Children)
				{
					if (element is DockablePane)
					{
						if (((DockablePane) element).Anchor == anchorStyle)
						{
							pane = (DockablePane) element;
						}
					}
				}

				if (pane == null)
				{
					// We have to add a new DockablePane
					pane = new DockablePane();
					if (anchorStyle == AnchorStyle.Top)
					{
						// Add the pane on top
						_viewManDock.VerticalResizingPanel.Children.Insert(0, pane);
					}
					else
					{
						// Add the pane at bottom
						_viewManDock.VerticalResizingPanel.Children.Add(pane);
					}
				}
			}
			else
			{
				// Search for a DockablePane with the given AnchorStyle
				foreach (UIElement element in _viewManDock.HorizontalResizingPanel.Children)
				{
					if (element is DockablePane)
					{
						if (((DockablePane) element).Anchor == anchorStyle)
						{
							pane = (DockablePane) element;
						}
					}
				}
				if (pane == null)
				{
					// We have to add a new DockablePane
					pane = new DockablePane();
					if (anchorStyle == AnchorStyle.Left)
					{
						// Add the pane on the left side
						_viewManDock.HorizontalResizingPanel.Children.Insert(0, pane);
					}
					else
					{
						// Add the pane on the right side
						_viewManDock.HorizontalResizingPanel.Children.Add(pane);
					}
				}
			}

			return pane;
		}

		private void SetBarItemVisibility(IView view, IView oldview, bool active)
		{
			bool suppressView = false;
			bool suppressSess = false;

			Type viewService = NQServiceManager.Instance.GetServiceInfoFromObject(view).ServiceInterface;
			Type viewSubstService = NQServiceManager.Instance.GetSubstitutingService(viewService);

			// Abort if the view or session service name is the same as the one of the old view
			if (oldview != null)
			{
				// Has the active view service name changed?
				Type viewServiceOld = NQServiceManager.Instance.GetServiceInfoFromObject(oldview).ServiceInterface;
				Type viewSubstServiceOld = NQServiceManager.Instance.GetSubstitutingService(viewServiceOld);
				suppressView = ((viewService == viewServiceOld) || ((viewSubstService != null) && (viewSubstService == viewSubstServiceOld)));
			}

			// Process bar bands and items dependent on a view
			if (!suppressView)
			{
				ProcessBarBands(viewService.FullName, BarItemConditionObject.View, active);
				ProcessBarItems(viewService.FullName, BarItemConditionObject.View, active);
				if (viewSubstService != null)
				{
					ProcessBarBands(viewSubstService.FullName, BarItemConditionObject.View, active);
					ProcessBarItems(viewSubstService.FullName, BarItemConditionObject.View, active);
				}
			}

			// Process bar bands and items dependent on a session
			if ((view != null) && (view.Session != null))
			{
				Type sessService = NQServiceManager.Instance.GetServiceInfoFromObject(view.Session).ServiceInterface;
				Type sessSubstService = NQServiceManager.Instance.GetSubstitutingService(sessService);

				if (oldview != null)
				{
					// Has the active session service name been changed?
					Type sessServiceOld = NQServiceManager.Instance.GetServiceInfoFromObject(oldview.Session).ServiceInterface;
					Type sessSubstOld = NQServiceManager.Instance.GetSubstitutingService(sessServiceOld);
					suppressSess = ((sessService == sessServiceOld) || ((sessSubstService != null) && (sessSubstService == sessSubstOld)));
				}

				if (!suppressSess)
				{
					ProcessBarBands(sessService.FullName, BarItemConditionObject.Session, active);
					ProcessBarItems(sessService.FullName, BarItemConditionObject.Session, active);
					if (viewSubstService != null)
					{
						ProcessBarBands(sessSubstService.FullName, BarItemConditionObject.Session, active);
						ProcessBarItems(sessSubstService.FullName, BarItemConditionObject.Session, active);
					}
				}
			}
		}

		private void ProcessBarBands(string serviceName, BarItemConditionObject condObject, bool active)
		{
			IBarItemDependency[] depItems;

			// Show/hide bar bands dependent on the active view
			depItems = _parentContainer.BarService.GetBandDependencies(condObject, serviceName);
			if (depItems != null)
			{
				foreach (IBarItemDependency itemdep in depItems)
				{
					IBarBand band = _parentContainer.BarService.GetBand(itemdep.Key);
					if (band != null)
					{
						band.HideAlways = !active;
					}
				}
			}
		}

		private void ProcessBarItems(string serviceName, BarItemConditionObject condObject, bool active)
		{
			IBarItemDependency[] depItems;

			// Show/hide bar items dependent on the active view
			depItems = _parentContainer.BarService.GetItemDependencies(condObject, serviceName);
			if (depItems != null)
			{
				foreach (IBarItemDependency itemdep in depItems)
				{
					IBarItem item = _parentContainer.BarService.GetItem(itemdep.Key);
					if (item != null)
					{
						if (itemdep.IsVisible)
						{
							item.ItemEnabled = active;
						}
						else
						{
							item.HideAlways = !active;
						}
					}
				}
			}
		}

		private void DockingManagerDeserializationCallback(object sender, DeserializationCallbackEventArgs e)
		{
			IList<ConfigData> lastOpenViews =
				_servPersist.GetContainerListSetting(_parentContainer.Name, "lastOpenViews");

			// Run through all list entries and recreate all document (!) views
			// Note: All other views are created in DockingManagerDeserializationCallback()
			if (lastOpenViews != null)
			{
				for (int i = 0; i < lastOpenViews.Count; i++)
				{
					string[] layoutSplit = lastOpenViews[i].RawData.Split(new char[] { '|' }, 7);
					if (layoutSplit.Length > 6)
					{
						if ((layoutSplit[1] == "1") && (e.Name == layoutSplit[0]))
						{
							// The view's data is separated by ANSI character 255 ("ÿ")
							string[] viewSplit = layoutSplit[6].Split('ÿ');
							if ((viewSplit != null) && (viewSplit.Length == 3))
							{
								// Create the new view instance
								ISessionManager sessionManager = ServiceCore
									.Get<Services.ISessionManagerService>()
									.To;
								ISession session = sessionManager[viewSplit[1]];
								if (session != null)
								{
									// Create the new view instance and set its context
									Type serviceIfcType = Type.GetType(viewSplit[0], false);
									if (serviceIfcType != null)
									{
										IView newView = ServiceCore
											.Create<IView>()
											.UsingType(serviceIfcType)
											.DependentOn<ISession>(session)
											.To;
										newView.Initialize(viewSplit[2]);

										// Add the view to view manager
										ManagedContent newContent = this.AddView(newView, true, false);
										if (newContent is DockableContent)
										{
											e.Content = (DockableContent) newContent;
										}
									}
								}
							}
						}
					}
				}
			}
		}

		private void LoadViewManagerLayout()
		{
			IList<ConfigData> lastOpenViews =
				_servPersist.GetContainerListSetting(_parentContainer.Name, "lastOpenViews");

			// Run through all list entries and recreate all document (!) views
			// Note: All other views are created in DockingManagerDeserializationCallback()
			if (lastOpenViews != null)
			{
				for (int i = 0; i < lastOpenViews.Count; i++)
				{
					string[] layoutSplit = lastOpenViews[i].RawData.Split(new char[] { '|' }, 7);
					if (layoutSplit.Length > 6)
					{
						// The view's data is separated by ANSI character 255 ("ÿ")
						string[] viewSplit = layoutSplit[6].Split('ÿ');
						if ((viewSplit != null) && (viewSplit.Length == 3))
						{
							if ((layoutSplit[1] == "0") || (layoutSplit[1] == "2"))
							{
								// Get the session instance
								ISessionManager sessionManager = ServiceCore
									.Get<Services.ISessionManagerService>()
									.To;
								ISession session = sessionManager[viewSplit[1]];
								if (session != null)
								{
									// Create the new view instance and set its context
									Type serviceIfcType = Type.GetType(viewSplit[0], false);
									if (serviceIfcType != null)
									{
										IView newView = ServiceCore
											.Create<IView>()
											.UsingType(serviceIfcType)
											.DependentOn<ISession>(session)
											.To;

										newView.Initialize(viewSplit[2]);

										// Set the saved display mode
										if (layoutSplit[1] == "2")
										{
											newView.DisplayMode = ViewDisplayMode.Floating;
										}
										else
										{
											newView.DisplayMode = ViewDisplayMode.InClientArea;
										}

										// Add the view to view manager
										this.AddView(newView, true);
									}
								}
							}
							else if (layoutSplit[1] == "1")
							{
								// We search for this view in the hidden section of the AvalonDock settings
								// This has to be done manually, since AvalonDock does not restore floating windows.
								XmlDocument xmlDoc = new XmlDocument();
								ConfigData layoutXML =
									_servPersist.GetContainerSetting(_parentContainer.Name, "viewManagerLayout");
								if (layoutXML != null)
								{
									xmlDoc.LoadXml(layoutXML.AsString());
									XmlNode dockContentNode = xmlDoc.SelectSingleNode("/DockingManager/Hidden/DockableContent[@Name='" + layoutSplit[0] + "']");
									if (dockContentNode != null)
									{
										// We have found an entry for this view in the hidden elements
										ISessionManager sessionManager = ServiceCore
											.Get<Services.ISessionManagerService>()
											.To;
										ISession session = sessionManager[viewSplit[1]];
										if (session != null)
										{
											// Create the new view instance and set its context
											Type serviceIfcType = Type.GetType(viewSplit[0], false);
											if (serviceIfcType != null)
											{
												IView newView = ServiceCore
													.Create<IView>()
													.UsingType(serviceIfcType)
													.DependentOn<ISession>(session)
													.To;

												newView.Initialize(viewSplit[2]);
												newView.DisplayMode = ViewDisplayMode.Floating;
												DockableContent dockContent = this.AddView(newView, true, true) as DockableContent;
												if (dockContent != null)
												{
													// Get the floating window for the DockContent
													FloatingWindow floatingWin = null;
													if (dockContent.ContainerPane != null)
													{
														floatingWin = dockContent.ContainerPane.Parent as FloatingWindow;
													}

													if (floatingWin != null)
													{
														// Parse the FloatingWindowSize value
														double height = 200;
														double width = 200;
														XmlNode floatingWinSizeAttr = dockContentNode.Attributes.GetNamedItem("FloatingWindowSize");
														if (floatingWinSizeAttr != null)
														{
															string[] locSplit = floatingWinSizeAttr.InnerText.Split(',');
															if (locSplit.Length > 1)
															{
																Double.TryParse(locSplit[0], out width);
																Double.TryParse(locSplit[1], out height);
																Size winsize = new Size(width, height);
																dockContent.FloatingWindowSize = winsize;
															}

															floatingWin.Width = width;
															floatingWin.Height = height;
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}

			// Load layout XML from persistence layer
			ConfigData layoutXml =
				_servPersist.GetContainerSetting(_parentContainer.Name, "viewManagerLayout");
			if (layoutXml != null)
			{
				MemoryStream memStream = null;
				StreamWriter writer = null;
				try
				{
					memStream = new MemoryStream();
					writer = new StreamWriter(memStream);
					writer.Write(layoutXml.AsString());
					writer.Flush();

					// Now let the DockPanel Suite load the settings from stream
					memStream.Seek(0, SeekOrigin.Begin);
					try
					{
						_viewManDock.DockingManager.RestoreLayout(memStream);
					}
					catch (Exception)
					{
					}
				}
				finally
				{
					if (writer != null)
					{
						writer.Close();
					}
					if (memStream != null)
					{
						memStream.Close();
					}
				}
			}

			// Activate the first restored DocumentContent
			if (_innerDocumentContents.Count > 0)
			{
				_innerDocumentContents[0].Activate();
			}
		}

		private void SaveViewManagerLayout()
		{
			IList<ConfigData> lastOpenViews = new List<ConfigData>();

			// Iterate through all open views
			int i = 1;
			foreach (IView openview in _views.Values)
			{
				// Save the layout settings for the view
				this.SaveViewLayout(openview);

				// Build the value with a temporary name
				string viewLayoutData = "LayoutView" + i.ToString();
				if (_dockableContents.ContainsKey(openview.Name))
				{
					_dockableContents[openview.Name].Name = viewLayoutData;
				}
				viewLayoutData += "|";

				if (openview.IsDocument)
				{
					if (openview.DisplayMode == ViewDisplayMode.Floating)
					{
						viewLayoutData += "2|";
					}
					else
					{
						viewLayoutData += "0|";
					}
				}
				else
				{
					viewLayoutData += "1|";
				}

				// Save window positions
				bool layoutDataAdded = false;
				if (openview.DisplayMode == ViewDisplayMode.Floating)
				{
					FloatingWindow floatingWin = null;

					if (_dockableContents.ContainsKey(openview.Name))
					{
						DockableContent dockContent = _dockableContents[openview.Name];
						if (dockContent.ContainerPane != null)
						{
							floatingWin = dockContent.ContainerPane.Parent as FloatingWindow;
							viewLayoutData += String.Format("{0}|{1}|{2}|{3}|", floatingWin.Left, floatingWin.Top, 0, 0);
							layoutDataAdded = true;
						}
					}
					else if (_documentContents.ContainsKey(openview.Name))
					{
						DocumentContent docContent = _documentContents[openview.Name];
						if (docContent.ContainerPane != null)
						{
							floatingWin = docContent.ContainerPane.Parent as FloatingWindow;
							viewLayoutData += String.Format("{0}|{1}|{2}|{3}|", floatingWin.Left, floatingWin.Top, floatingWin.Width, floatingWin.Height);
							layoutDataAdded = true;
						}
					}
				}

				if (!layoutDataAdded)
				{
					// Add dummy data
					viewLayoutData += "0|0|0|0|";
				}

				// Save view service name, session name and view's context
				viewLayoutData += NQServiceManager.Instance.GetServiceInfoFromObject(openview).ServiceInterface.AssemblyQualifiedName + "ÿ"
					+ openview.Session.SessionName + "ÿ"
					+ openview.Context;

				lastOpenViews.Add(new ConfigData().FromString(viewLayoutData));

				i++;
			}

			// Save the layout setting list
			_servPersist.SetContainerListSetting(_parentContainer.Name, "lastOpenViews", lastOpenViews);

			string dockXml = String.Empty;
			MemoryStream memStream = null;
			StreamReader reader = null;
			try
			{
				// Read DockPanel's XML output into a memory stream
				memStream = new MemoryStream();
				_viewManDock.DockingManager.SaveLayout(memStream);
				reader = new StreamReader(memStream);
				memStream.Seek(0, SeekOrigin.Begin);
				dockXml = reader.ReadToEnd();

				// Save as a setting item
				_servPersist.SetContainerSetting(
					_parentContainer.Name, "viewManagerLayout", new ConfigData().FromString(dockXml));
			}
			finally
			{
				if (reader != null)
				{
					reader.Close();
				}
				if (memStream != null)
				{
					memStream.Close();
				}
			}
		}

		private void LoadViewLayout(IView view)
		{
			IList<ConfigData> viewLayout =
				_servPersist.GetContainerListSetting(_parentContainer.Name, "viewLayout");

			if (viewLayout != null)
			{
				// Look for the view layout entry
				string viewServName = NQServiceManager.Instance.GetServiceInfoFromObject(view).ServiceInterface.FullName;
				for (int i = 0; i < viewLayout.Count; i++)
				{
					if (viewLayout[i].RawData.StartsWith(viewServName + "|"))
					{
						string[] layoutSplit = viewLayout[i].RawData.Split('|');
						if (layoutSplit.Length > 1)
						{
							switch (layoutSplit[1])
							{
								case "i":
									view.DisplayMode = ViewDisplayMode.InClientArea;
									break;
								case "f":
									view.DisplayMode = ViewDisplayMode.Floating;
									break;
								case "t":
									view.DisplayMode = ViewDisplayMode.DockedTop;
									break;
								case "b":
									view.DisplayMode = ViewDisplayMode.DockedBottom;
									break;
								case "r":
									view.DisplayMode = ViewDisplayMode.DockedRight;
									break;
								case "l":
									view.DisplayMode = ViewDisplayMode.DockedLeft;
									break;
								default:
									view.DisplayMode = ViewDisplayMode.Floating;
									break;
							}
						}
						break;
					}
				}
			}
		}

		private void SaveViewLayout(IView view)
		{
			IList<ConfigData> viewLayout =
				_servPersist.GetContainerListSetting(_parentContainer.Name, "viewLayout");
			if (viewLayout == null)
			{
				viewLayout = new List<ConfigData>();
			}

			string viewServName = NQServiceManager.Instance.GetServiceInfoFromObject(view).ServiceInterface.FullName;

			int layoutIndex = -1;
			// Look out for an already created layout entry
			for (int i = 0; i < viewLayout.Count; i++)
			{
				if (viewLayout[i].RawData.StartsWith(viewServName + "|"))
				{
					layoutIndex = i;
					break;
				}
			}
			if (layoutIndex == -1)
			{
				// We must create a new layout entry (view service has not been opened yet in this container)
				viewLayout.Add(null);
				layoutIndex = viewLayout.Count - 1;
			}

			// Now set the layout entry
			string layoutData = viewServName + "|";
			switch (view.DisplayMode)
			{
				case ViewDisplayMode.InClientArea:
					layoutData += "i";
					break;
				case ViewDisplayMode.Floating:
					layoutData += "f";
					break;
				case ViewDisplayMode.DockedLeft:
					layoutData += "l";
					break;
				case ViewDisplayMode.DockedRight:
					layoutData += "r";
					break;
				case ViewDisplayMode.DockedBottom:
					layoutData += "b";
					break;
				case ViewDisplayMode.DockedTop:
					layoutData += "t";
					break;
				default:
					layoutData += "f";
					break;
			}

			viewLayout[layoutIndex] = new ConfigData().FromString(layoutData);
			_servPersist.SetContainerListSetting(_parentContainer.Name, "viewLayout", viewLayout);
		}

		private DockableStyle DockableStyleFromDisplayModes(ViewDisplayMode displayMode)
		{
			DockableStyle result = DockableStyle.None;

			if ((displayMode & ViewDisplayMode.InClientArea) == ViewDisplayMode.InClientArea)
			{
				result |= DockableStyle.Document;
			}

			if ((displayMode & ViewDisplayMode.DockedLeft) == ViewDisplayMode.DockedLeft)
			{
				result |= DockableStyle.LeftBorder;
			}

			if ((displayMode & ViewDisplayMode.DockedRight) == ViewDisplayMode.DockedRight)
			{
				result |= DockableStyle.RightBorder;
			}

			if ((displayMode & ViewDisplayMode.Floating) == ViewDisplayMode.Floating)
			{
				result |= DockableStyle.Floating;
			}

			result |= DockableStyle.AutoHide;

			return result;
		}

		private ViewDisplayMode GetDisplayModeFromDockableState(DockableContentState dockableState, AnchorStyle anchorStyle)
		{
			if ((dockableState & DockableContentState.Document) == DockableContentState.Document)
			{
				return ViewDisplayMode.InClientArea;
			}
			else if (((dockableState & DockableContentState.DockableWindow) == DockableContentState.DockableWindow)
				|| ((dockableState & DockableContentState.FloatingWindow) == DockableContentState.FloatingWindow))
			{
				return ViewDisplayMode.Floating;
			}
			else if ((dockableState & DockableContentState.Docked) == DockableContentState.Docked)
			{
				switch (anchorStyle)
				{
					case AnchorStyle.Left:
						return ViewDisplayMode.DockedLeft;
					case AnchorStyle.Right:
						return ViewDisplayMode.DockedRight;
					case AnchorStyle.Bottom:
						return ViewDisplayMode.DockedBottom;
					case AnchorStyle.Top:
						return ViewDisplayMode.InClientArea;
					default:
						// TODO This is only a dirty workaround, AvalonDock seems to not set the Anchor property correctly!
						return ViewDisplayMode.DockedLeft;
				}
			}

			return ViewDisplayMode.Floating;
		}

		private void GetDockableStateFromDisplayMode(ViewDisplayMode displayMode, ref DockableContentState dockableState, ref AnchorStyle anchorStyle)
		{
			switch (displayMode)
			{
				case ViewDisplayMode.InClientArea:
					dockableState = DockableContentState.Document;
					break;
				case ViewDisplayMode.Floating:
					dockableState = DockableContentState.DockableWindow;
					break;
				case ViewDisplayMode.DockedLeft:
					dockableState = DockableContentState.Docked;
					anchorStyle = AnchorStyle.Left;
					break;
				case ViewDisplayMode.DockedRight:
					dockableState = DockableContentState.Docked;
					anchorStyle = AnchorStyle.Right;
					break;
				case ViewDisplayMode.DockedBottom:
					dockableState = DockableContentState.Docked;
					anchorStyle = AnchorStyle.Bottom;
					break;
			}
		}

		private void CreateMenus()
		{
			IBarBand mainMenu = _servBar.GetMenuBand();

			// Add main window menu
			Stream xmlstream = Assembly.GetExecutingAssembly().GetManifestResourceStream("AWZhome.NQ.CommonServices.menudef.ViewManager.xml");
			_parentContainer.BarService.CreateItemsFromXml(xmlstream);
			xmlstream.Close();
		}

		private void RaiseViewNotFoundException(string viewName)
		{
			throw new Exception("View " + viewName + " not found.");
		}

		#endregion
	}
}
